#import "AFNetWorkUtils.h"
#import "AFNetWorking.h"
#import "AFNetworkActivityIndicatorManager.h"
#import "ZYAPIClient.h"


NSString *const netWorkUtilsDomain = @"http://AFNetWorkUtils";

NSString *const operationInfoKey = @"operationInfoKey";

@implementation AFNetWorkUtils

DEFINE_SINGLETON_IMPLEMENTATION(AFNetWorkUtils)

- (void)setUp {
    self.netType = WiFiNet;
    self.netTypeString = @"WIFI";
}

/**
 * 创建网络请求管理类单例对象
 */
+ (AFHTTPSessionManager *)sharedHTTPOperationManager {
    static AFHTTPSessionManager *manager = nil;
//    static ZYAPIClient *manager = nil;
    static dispatch_once_t pred;
    dispatch_once(&pred, ^{
        NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
        manager = [[AFHTTPSessionManager manager]initWithBaseURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/",ZYAPI_BASE_URL]] sessionConfiguration:sessionConfiguration];
//        manager = [AFHTTPSessionManager manager];
//        manager = [ZYAPIClient sharedClient];
        manager.requestSerializer.timeoutInterval = 20.f;//超时时间为20s
        NSMutableSet *acceptableContentTypes = [NSMutableSet setWithSet:manager.responseSerializer.acceptableContentTypes];
        [manager.requestSerializer setValue:@"Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A365 Safari/600.1.4" forHTTPHeaderField:@"User-Agent"];
////        // 创建安全策略对象
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
        // 设置允许信任非法证书
        securityPolicy.allowInvalidCertificates = YES;
        // 设置禁止域名校验
        securityPolicy.validatesDomainName = NO;
        // 将创建的 安全策略 赋值给 manager
        manager.securityPolicy = securityPolicy;
        manager.responseSerializer.acceptableContentTypes = acceptableContentTypes;
    });
    return manager;
}

- (void)startMonitoring {
    [[self startMonitoringNet] subscribeNext:^(id x) {
    }];
}

- (RACSignal *)startMonitoringNet {
    [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
    AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager];
    [mgr startMonitoring];
    ZYWeakSelf(ws)
    return [[RACSignal createSignal:^RACDisposable *(id <RACSubscriber> subscriber) {
        [mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
            switch (status) {
                case AFNetworkReachabilityStatusReachableViaWiFi:
                    ws.netType = WiFiNet;
                    self.netType = WiFiNet;
                    self.netTypeString = @"WIFI";
                    break;
                    
                case AFNetworkReachabilityStatusReachableViaWWAN:
                    ws.netType = OtherNet;
                    ws.netTypeString = @"2G/3G/4G";
                    break;
                    
                case AFNetworkReachabilityStatusNotReachable:
                    ws.netType = NONet;
                    ws.netTypeString = @"网络已断开";
                    //                    [[pod 'SDWebImage', '~>3.8' sharedManager] cancelAll];
                    //                    [[YYWebImageManager sharedManager] ]
                    break;
                    
                case AFNetworkReachabilityStatusUnknown:
                    ws.netType = NONet;
                    ws.netTypeString = @"其他情况";
                    break;
                default:
                    break;
            }
            [subscriber sendNext:ws.netTypeString];
            [subscriber sendCompleted];
        }];
        return nil;
    }] setNameWithFormat:@"<%@: %p> -startMonitoringNet", self.class, self];
}

#pragma mark -RAC

/**
 *  转换成响应式请求 可重用
 *
 *  @param url   请求地址
 *  @param params 请求参数
 *
 *  @return 带请求结果（字典）的信号
 */
+ (RACSignal *)racPOSTWithURL:(NSString *)url params:(NSDictionary *)params {
    if ([AFNetWorkUtils sharedAFNetWorkUtils].netType == NONet) {
        return [self getNoNetSignal];
    }
    NSLog(@"url:%@",url);
    NSLog(@"params:%@",params);
    return [[RACSignal createSignal:^RACDisposable *(id <RACSubscriber> subscriber) {
        
        AFHTTPSessionManager *manager = [self sharedHTTPOperationManager];
        NSURLSessionDataTask *task = [manager POST:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            [self handleResultWithSubscriber:(id <RACSubscriber>) subscriber operation:task responseObject:responseObject];
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            [self handleErrorResultWithSubscriber:(id <RACSubscriber>) subscriber operation:task error:error];
        }];
        //        NSURLSessionDataTask *operation = [manager POST:url parameters:params success:^(NSURLSessionDataTask *operation, id responseObject) {
        //            [self handleResultWithSubscriber:(id <RACSubscriber>) subscriber operation:operation responseObject:responseObject];
        //        }                                         failure:^(NSURLSessionDataTask *operation, NSError *error) {
        //            [self handleErrorResultWithSubscriber:(id <RACSubscriber>) subscriber operation:operation error:error];
        //        }];
        return [RACDisposable disposableWithBlock:^{
            [task cancel];
        }];
    }] setNameWithFormat:@"<%@: %p> -post2racWithURL: %@, params: %@", self.class, self, url, params];
}

+ (RACSignal *)racGETWithURL:(NSString *)url {
    return [[self racGETWithURL:url isJSON:YES params:nil] setNameWithFormat:@"<%@: %p> -get2racWithURL: %@", self.class, self, url];
}

+ (RACSignal *)racGETUNJSONWithURL:(NSString *)url {
    return [[self racGETWithURL:url isJSON:NO params:nil] setNameWithFormat:@"<%@: %p> -get2racUNJSONWithURL: %@", self.class, self, url];
}

+ (RACSignal *)racGETWithURL:(NSString *)url params:(NSDictionary *)params{
    NSLog(@"url:%@",url);
    NSLog(@"params:%@",params);
    return [[self racGETWithURL:url isJSON:YES params:params] setNameWithFormat:@"<%@: %p> -get2racWithURL: %@", self.class, self, url];
}

+ (RACSignal *)racGETWithURL:(NSString *)url params:(NSDictionary *)params class:(Class)clazz{
    if ([AFNetWorkUtils sharedAFNetWorkUtils].netType == NONet) {
        return [self getNoNetSignal];
    }
    //有网络
    return [[[[self racGETWithURL:url params:params] map:^id(id responseObject) {
        if ([responseObject isKindOfClass:[NSArray class]]) {
            return [NSArray modelArrayWithClass:clazz json:responseObject];
        } else {
            return [clazz modelWithJSON:responseObject];
        }
    }] replayLazily] setNameWithFormat:@"<%@: %p> -racGETWithURL: %@,class: %@", self.class, self, url, NSStringFromClass(clazz)];
}

+ (RACSignal *)racGETWithURL:(NSString *)url isJSON:(BOOL)isJSON params:(NSDictionary *)params{
    if ([AFNetWorkUtils sharedAFNetWorkUtils].netType == NONet) {
        return [self getNoNetSignal];
    }
    return [RACSignal createSignal:^RACDisposable *(id <RACSubscriber> subscriber) {
        AFHTTPSessionManager *manager = [self sharedHTTPOperationManager];
        if (!isJSON) {
            manager = [AFHTTPSessionManager manager];
            manager.responseSerializer = [AFHTTPResponseSerializer serializer];
        }
        NSURLSessionDataTask *task = [manager GET:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            if (!isJSON) {
                [subscriber sendNext:responseObject];
                [subscriber sendCompleted];
                return;
            }
            [self handleResultWithSubscriber:(id <RACSubscriber>) subscriber operation:task responseObject:responseObject];
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            if (!isJSON) {
                [subscriber sendNext:error];
                return;
            }
            [self handleErrorResultWithSubscriber:(id <RACSubscriber>) subscriber operation:task error:error];
        }];
        return [RACDisposable disposableWithBlock:^{
            [task cancel];
        }];
    }];
}

+ (RACSignal *)racDeleteWithURL:(NSString *)url isJSON:(BOOL)isJSON params:(NSDictionary *)params{
    if ([AFNetWorkUtils sharedAFNetWorkUtils].netType == NONet) {
        return [self getNoNetSignal];
    }
    return [RACSignal createSignal:^RACDisposable *(id <RACSubscriber> subscriber) {
        AFHTTPSessionManager *manager = [self sharedHTTPOperationManager];
        if (!isJSON) {
            manager = [AFHTTPSessionManager manager];
            manager.responseSerializer = [AFHTTPResponseSerializer serializer];
        }
        NSURLSessionDataTask *task = [manager DELETE:url parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            if (!isJSON) {
                [subscriber sendNext:responseObject];
                [subscriber sendCompleted];
                return;
            }
            [self handleResultWithSubscriber:(id <RACSubscriber>) subscriber operation:task responseObject:responseObject];
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            if (!isJSON) {
                [subscriber sendNext:error];
                return;
            }
            [self handleErrorResultWithSubscriber:(id <RACSubscriber>) subscriber operation:task error:error];
        }];
        return [RACDisposable disposableWithBlock:^{
            [task cancel];
        }];
    }];
}

/**
 *  响应式post请求 返回处理后的结果 对象类型 可重用
 *
 *  @param url   请求地址
 *  @param params 请求参数
 *  @param clazz  字典对应的对象
 *
 *  @return 带请求结果（对象）的信号
 */
+ (RACSignal *)racPOSTWithURL:(NSString *)url params:(NSDictionary *)params class:(Class)clazz {
    if ([AFNetWorkUtils sharedAFNetWorkUtils].netType == NONet) {
        return [self getNoNetSignal];
    }
    //有网络
    return [[[[self racPOSTWithURL:url params:params] map:^id(id responseObject) {
        if ([responseObject isKindOfClass:[NSArray class]]) {
            return [NSArray modelArrayWithClass:clazz json:responseObject];
        } else {
            return [clazz modelWithJSON:responseObject];
        }
    }] replayLazily] setNameWithFormat:@"<%@: %p> -racPOSTWithURL: %@, params: %@ class: %@", self.class, self, url, params, NSStringFromClass(clazz)];
}


+ (RACSignal *)racGETWithURL:(NSString *)url class:(Class)clazz {
    if ([AFNetWorkUtils sharedAFNetWorkUtils].netType == NONet) {
        return [self getNoNetSignal];
    }
    //有网络
    return [[[[self racGETWithURL:url] map:^id(id responseObject) {
        if ([responseObject isKindOfClass:[NSArray class]]) {
            return [NSArray modelArrayWithClass:clazz json:responseObject];
            //            NSMutableArray *tempArr = [NSMutableArray array];
            //            for (NSDictionary *dict in responseObject) {
            //                id item = [clazz modelWithDictionary:dict];
            //                [tempArr addObject:item];
            //            }
            //            return tempArr;
        } else {
            return [clazz modelWithJSON:responseObject];
        }
    }] replayLazily] setNameWithFormat:@"<%@: %p> -racGETWithURL: %@,class: %@", self.class, self, url, NSStringFromClass(clazz)];
}

+ (RACSignal *)getNoNetSignal {
    return [[RACSignal createSignal:^RACDisposable *(id <RACSubscriber> subscriber) {
        [subscriber sendError:[NSErrorHelper createErrorWithDomain:netWorkUtilsDomain code:kCFURLErrorNotConnectedToInternet]];
        return nil;
    }] setNameWithFormat:@"<%@: %p> -getNoNetSignal", self.class, self];
}

+ (void)handleErrorResultWithSubscriber:(id <RACSubscriber>)subscriber operation:(NSURLSessionDataTask *)operation error:(NSError *)error {
    NSLog(@"error: %@",[NSErrorHelper handleErrorMessage:error]);
    NSMutableDictionary *userInfo = [error.userInfo mutableCopy] ?: [NSMutableDictionary dictionary];
    userInfo[operationInfoKey] = operation;
    userInfo[customErrorInfoKey] = [NSErrorHelper handleErrorMessage:error];
    [subscriber sendError:[NSErrorHelper createErrorWithUserInfo:userInfo domain:netWorkUtilsDomain]];
}

+ (void)handleResultWithSubscriber:(id <RACSubscriber>)subscriber operation:(NSURLSessionDataTask *)operation responseObject:(NSDictionary *)responseObject {
    //在此根据自己应用的接口进行统一处理
    NSLog(@"%@",responseObject);
    NSString *code = [responseObject objectForKey:@"code"];
    if([code integerValue] !=200){
//        if([[responseObject objectForKey:@"message"] isEqualToString:@"用户未登录"]){
//            [subscriber sendError:[NSErrorHelper createErrorWithErrorInfo:LOGIN_FAILURE]];
//        }else{
//            [subscriber sendError:[NSErrorHelper createErrorWithErrorInfo:[responseObject objectForKey:@"message"] ]];
//        }
        if([code integerValue] == 301){
            [subscriber sendError:[NSErrorHelper createErrorWithErrorInfo:LOGIN_FAILURE]];
            return;
        }
        if([code integerValue] == 5003){
            [subscriber sendNext:responseObject];
            return;
        }
        NSString *errorMessage = [[ZYChangeLanguage sharedZYChangeLanguage] getStringByKey:[NSString stringWithFormat:@"code_%@",code]];
        [subscriber sendError:[NSErrorHelper createErrorWithErrorInfo:errorMessage]];
        [subscriber sendCompleted];
        return;
    }else{
        [subscriber sendNext:responseObject];
    }
    [subscriber sendCompleted];
    //示例(测试接口)
    //    NSInteger count = [[responseObject objectForKey:@"count"] integerValue];
    //    if (!count) {
    //        [subscriber sendNext:responseObject];
    //        [subscriber sendCompleted];
    //        return;
    //    }
    //
    //
    //    //统一格式接口
    //    NSString * status = [responseObject objectForKey:@"status"];
    //    if ([status isEqualToString:@"ok"]) {
    //        //  [subscriber sendNext:RACTuplePack(operation,responseObject)];
    //        [subscriber sendNext:responseObject];
    //        [subscriber sendCompleted];
    //    } else {//正确返回，带有错误信息
    //        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    //        userInfo[operationInfoKey] = operation;
    //        BOOL isError = [status isEqualToString:@"error"];
    //        NSString * errorInfo = isError ? [responseObject objectForKey:@"error"] : @"请求没有得到处理";
    //        userInfo[customErrorInfoKey] = errorInfo;
    //        NSError * error = [NSErrorHelper createErrorWithUserInfo:userInfo domain:netWorkUtilsDomain];
    //        [subscriber sendError:error];
    //    }
}

@end
